import json
import datetime
from django.db import models


class BaseModel(models.Model):
    """
    模型基类
    增加了审计字段
    增加了model转为json的方法
    """
    creator = models.CharField(max_length=50, null=True, blank=True, verbose_name='创建人', help_text="创建人")
    create_datetime = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name="创建时间", help_text="创建时间")
    modifier = models.CharField(max_length=50, null=True, blank=True, verbose_name="修改人", help_text="修改人")
    modify_datetime = models.DateTimeField(auto_now=True, null=True, blank=True, verbose_name="修改时间", help_text="修改时间")
    DELETE_CHOICES = (
        (0, "否"),
        (1, "是"),
    )
    is_delete = models.IntegerField(choices=DELETE_CHOICES, default=0, verbose_name='是否删除', help_text="是否删除")
    description = models.CharField(max_length=255, null=True, blank=True, verbose_name="描述", help_text="描述")
    dept_belong_id = models.CharField(max_length=255, null=True, blank=True, verbose_name="数据归属部门", help_text="数据归属部门")

    class Meta:
        abstract = True
        verbose_name = '基础模型'
        verbose_name_plural = verbose_name

    def is_attr_instance(self, attr, clazz):
        return isinstance(getattr(self, attr), clazz)

    # 返回self._meta.fields中没有的，但是又需要的字段名列表
    # 形如['name','request_method']
    def get_meta_fields(self):
        pass

    # 返回需要在json中忽略的字段名列表
    # 形如['password']
    def get_ignore_fields(self):
        pass

    def get_dict(self):
        fields = []
        for field in self._meta.fields:
            fields.append(field.name)

        d = {}
        for attr in fields:
            if isinstance(getattr(self, attr), datetime.datetime):
                d[attr] = getattr(self, attr).strftime('%Y-%m-%d %H:%M:%S')
            elif isinstance(getattr(self, attr), datetime.date):
                d[attr] = getattr(self, attr).strftime('%Y-%m-%d')
            # 特殊处理datetime的数据
            elif isinstance(getattr(self, attr), BaseModel):
                d[attr] = getattr(self, attr).get_dict()
            # 递归生成BaseModel类的dict
            elif self.is_attr_instance(attr, int) or self.is_attr_instance(attr, float) \
                    or self.is_attr_instance(attr, str):
                d[attr] = getattr(self, attr)
            # else:
            #     d[attr] = getattr(self, attr)

        meta_fields = self.get_meta_fields()
        if meta_fields is not None:
            for m in meta_fields:
                if hasattr(self, m):
                    attlist = getattr(self, m).all()
                    l = []
                    for attr in attlist:
                        if isinstance(attr, BaseModel):
                            l.append(attr.get_dict())
                        else:
                            dic = attr.__dict__
                            if '_state' in dic:
                                dic.pop('_state')
                            l.append(dic)
                    d[m] = l
        # 由于ManyToMany类不能存在于_meat.fields，因而子类需要在getMtMFiled中返回这些字段
        if 'basemodel_ptr' in d:
            d.pop('basemodel_ptr')

        ignore_fields = self.get_ignore_fields()
        if ignore_fields is not None:
            for m in ignore_fields:
                if d.get(m) is not None:
                    d.pop(m)
        # 移除不需要的字段
        return d

    def to_json(self):
        return json.dumps(self.get_dict(), ensure_ascii=False).encode('utf-8').decode()
